// import com.alibaba.druid.DbType;
// import com.alibaba.druid.sql.ast.*;
// import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
// import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
// import com.alibaba.druid.sql.visitor.SQLASTVisitor;

// import java.util.ArrayList;
// import java.util.List;

#include "SQLAlterTableStatement.h"
#include "SQLAlterTableItem.h"
#include "../../visitor/SQLASTVisitor.h"
#include "../../../utils/listTran.h"
#include "../../../utils/instanceof.h"
#include "../expr/SQLIdentifierExpr.h"
#include "../expr/SQLPropertyExpr.h"
#include "SQLExprTableSource.h"

SQLAlterTableStatement::SQLAlterTableStatement()
{
  items = std::make_shared<std::list<SQLAlterTableItem_ptr>>();
  tableOptions = std::make_shared<std::list<SQLAssignItem_ptr>>();
  clusteredBy = std::make_shared<std::list<SQLSelectOrderByItem_ptr>>();
  sortedBy = std::make_shared<std::list<SQLSelectOrderByItem_ptr>>();
}

SQLAlterTableStatement::SQLAlterTableStatement(DbType_ptr dbType)
    : SQLStatementImpl(dbType)
{
  items = std::make_shared<std::list<SQLAlterTableItem_ptr>>();
  tableOptions = std::make_shared<std::list<SQLAssignItem_ptr>>();
  clusteredBy = std::make_shared<std::list<SQLSelectOrderByItem_ptr>>();
  sortedBy = std::make_shared<std::list<SQLSelectOrderByItem_ptr>>();
}

BOOL_ptr SQLAlterTableStatement::isIgnore()
{
  return ignore;
}

void SQLAlterTableStatement::setIgnore(BOOL_ptr ignore)
{
  this->ignore = ignore;
}

BOOL_ptr SQLAlterTableStatement::isOnline()
{
  return online;
}

void SQLAlterTableStatement::setOnline(BOOL_ptr online)
{
  this->online = online;
}

BOOL_ptr SQLAlterTableStatement::isOffline()
{
  return offline;
}

void SQLAlterTableStatement::setOffline(BOOL_ptr offline)
{
  this->offline = offline;
}

BOOL_ptr SQLAlterTableStatement::isIfExists()
{
  return ifExists;
}

void SQLAlterTableStatement::setIfExists(BOOL_ptr ifExists)
{
  this->ifExists = ifExists;
}

BOOL_ptr SQLAlterTableStatement::isRemovePatiting()
{
  return removePatiting;
}

void SQLAlterTableStatement::setRemovePatiting(BOOL_ptr removePatiting)
{
  this->removePatiting = removePatiting;
}

BOOL_ptr SQLAlterTableStatement::isUpgradePatiting()
{
  return upgradePatiting;
}

void SQLAlterTableStatement::setUpgradePatiting(BOOL_ptr upgradePatiting)
{
  this->upgradePatiting = upgradePatiting;
}

BOOL_ptr SQLAlterTableStatement::isUpdateGlobalIndexes()
{
  return updateGlobalIndexes;
}

void SQLAlterTableStatement::setUpdateGlobalIndexes(BOOL_ptr updateGlobalIndexes)
{
  this->updateGlobalIndexes = updateGlobalIndexes;
}

BOOL_ptr SQLAlterTableStatement::isInvalidateGlobalIndexes()
{
  return invalidateGlobalIndexes;
}

void SQLAlterTableStatement::setInvalidateGlobalIndexes(BOOL_ptr invalidateGlobalIndexes)
{
  this->invalidateGlobalIndexes = invalidateGlobalIndexes;
}

BOOL_ptr SQLAlterTableStatement::isMergeSmallFiles()
{
  return mergeSmallFiles;
}

void SQLAlterTableStatement::setMergeSmallFiles(BOOL_ptr mergeSmallFiles)
{
  this->mergeSmallFiles = mergeSmallFiles;
}

SQLAlterTableItem_list_ptr SQLAlterTableStatement::getItems()
{
  return items;
}

void SQLAlterTableStatement::addItem(SQLAlterTableItem_ptr item)
{
  if (item != nullptr)
  {
    item->setParent(SharedObject(SQLAlterTableStatement));
  }
  this->items->push_back(item);
}

SQLExprTableSource_ptr SQLAlterTableStatement::getTableSource()
{
  return tableSource;
}

void SQLAlterTableStatement::setTableSource(SQLExprTableSource_ptr tableSource)
{
  this->tableSource = tableSource;
}

void SQLAlterTableStatement::setTableSource(SQLExpr_ptr table)
{
  this->setTableSource(SQLExprTableSource_ptr(new SQLExprTableSource(table)));
}

SQLName_ptr SQLAlterTableStatement::getName()
{
  if (getTableSource() == nullptr)
  {
    return nullptr;
  }
  return std::dynamic_pointer_cast<SQLName>(getTableSource()->getExpr());
}

long SQLAlterTableStatement::nameHashCode64()
{
  if (getTableSource() == nullptr)
  {
    return 0L;
  }
  return (std::dynamic_pointer_cast<SQLName>(getTableSource()->getExpr()))->nameHashCode64();
}

void SQLAlterTableStatement::setName(SQLName_ptr name)
{
  this->setTableSource(SQLExprTableSource_ptr(new SQLExprTableSource(name)));
}

SQLAssignItem_list_ptr SQLAlterTableStatement::getTableOptions()
{
  return tableOptions;
}

SQLPartitionBy_ptr SQLAlterTableStatement::getPartition()
{
  return partition;
}

void SQLAlterTableStatement::setPartition(SQLPartitionBy_ptr partition)
{
  this->partition = partition;
}

// @Override
void SQLAlterTableStatement::accept0(SQLASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(SQLAlterTableStatement)))
  {
    acceptChild(visitor, getTableSource());
    SQLObject_list_ptr tmp = ListTran::tran_class<SQLAlterTableItem, SQLObject>(getItems());
    acceptChild(visitor, tmp);
  }
  visitor->endVisit(SharedObject(SQLAlterTableStatement));
}

// @Override
SQLObject_list_ptr SQLAlterTableStatement::getChildren()
{
  SQLObject_list_ptr children = std::make_shared<std::list<SQLObject_ptr>>();
  if (tableSource != nullptr)
  {
    children->push_back(tableSource);
  }
  // children.addAll(this->items);
  for (auto item : *this->items)
  {
    children->push_back(item);
  }
  return children;
}

string_ptr SQLAlterTableStatement::getTableName()
{
  if (tableSource == nullptr)
  {
    return nullptr;
  }
  SQLExpr_ptr expr = (std::dynamic_pointer_cast<SQLExprTableSource>(tableSource))->getExpr();
  if (instanceof <SQLExpr, SQLIdentifierExpr>(expr))
  {
    return (std::dynamic_pointer_cast<SQLIdentifierExpr>(expr))->getName();
  }
  else if (instanceof <SQLExpr, SQLPropertyExpr>(expr))
  {
    return (std::dynamic_pointer_cast<SQLPropertyExpr>(expr))->getName();
  }

  return nullptr;
}

string_ptr SQLAlterTableStatement::getSchema()
{
  SQLName_ptr name = getName();
  if (name == nullptr)
  {
    return nullptr;
  }

  if (instanceof<SQLName,SQLPropertyExpr>(name)  )
  {
    return (std::dynamic_pointer_cast<SQLPropertyExpr>(name))->getOwnernName();
  }

  return nullptr;
}

void SQLAlterTableStatement::setItems(SQLAlterTableItem_list_ptr items)
{
  this->items = items;
}

BOOL_ptr SQLAlterTableStatement::isRange()
{
  return range;
}

void SQLAlterTableStatement::setRange(BOOL_ptr range)
{
  this->range = range;
}

SQLSelectOrderByItem_list_ptr SQLAlterTableStatement::getClusteredBy()
{
  return clusteredBy;
}

void SQLAlterTableStatement::addClusteredByItem(SQLSelectOrderByItem_ptr item)
{
  item->setParent(SharedObject(SQLAlterTableStatement));
  this->clusteredBy->push_back(item);
}

SQLSelectOrderByItem_list_ptr SQLAlterTableStatement::getSortedBy()
{
  return sortedBy;
}

void SQLAlterTableStatement::addSortedByItem(SQLSelectOrderByItem_ptr item)
{
  item->setParent(SharedObject(SQLAlterTableStatement));
  this->sortedBy->push_back(item);
}

int SQLAlterTableStatement::getBuckets()
{
  return buckets;
}

void SQLAlterTableStatement::setBuckets(int buckets)
{
  this->buckets = buckets;
}

int SQLAlterTableStatement::getShards()
{
  return shards;
}

void SQLAlterTableStatement::setShards(int shards)
{
  this->shards = shards;
}

BOOL_ptr SQLAlterTableStatement::isNotClustered()
{
  return notClustered;
}

void SQLAlterTableStatement::setNotClustered(BOOL_ptr notClustered)
{
  this->notClustered = notClustered;
}

// @Override
SQLDDLStatement::DDLObjectType SQLAlterTableStatement::getDDLObjectType()
{
  return SQLDDLStatement::DDLObjectType::TABLE;
}

SQLName_ptr SQLAlterTableStatement::getOn()
{
  return on;
}

void SQLAlterTableStatement::setOn(SQLName_ptr x)
{
  if (x != nullptr)
  {
    x->setParent(SharedObject(SQLAlterTableStatement));
  }
  this->on = x;
}
